//
//  IGOSSManager.m
//  jingdongfang
//
//  Created by BOE on 2017/9/12.
//  Copyright © 2017年 LJL. All rights reserved.
//

#import "IGOSSManager.h"
#import "NSString+Extension.h"
#import <AliyunOSSiOS/OSSService.h>
#import "TZImageManager.h"

@interface IGOSSManager()

@property (nonatomic, strong) IGImageToken *imageToken;
@property (nonatomic, strong) OSSClient *client;
@property (nonatomic, strong) OSSPutObjectRequest *putRequest;
@property (nonatomic, assign) IGAliYunFolderType type;

@property (assign, nonatomic) BOOL isRequesting;

@end

@implementation IGOSSManager

+ (instancetype)sharedManager {
    
    static IGOSSManager *manager = nil;
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[IGOSSManager alloc] init];
    });
    return manager;
}

//校验imageToken是否过期 过期-->YES  未过期-->NO
- (BOOL)checkImageTokenExpiration {
    //当前时间
    NSDate *date = [NSDate date];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    //token过期时间
    NSDate *expiration = [formatter dateFromString:self.imageToken.expiration];
    if (expiration && [NSDate compareOneDay:date withAnotherDay:expiration] == -1) {//未过期
        return NO;
    }
    return YES;
}

- (void)requestOssToken:(IGAliYunFolderType)type {
    [self requestOssToken:type withCheckExpiration:YES];
}

- (void)requestOssToken:(IGAliYunFolderType)type withCheckExpiration:(BOOL)checkExpiration {
    self.type = type;
    
    if (checkExpiration) {
        //校验imageToken是否过期
        if (![self checkImageTokenExpiration]) {//未过期
            [self.imageToken configBucketPath:type];
            return;
        }
    }
    
    if (self.isRequesting) {
        return;
    }
    
    self.isRequesting = YES;
    __weak typeof(self) weakSelf = self;
    IGImageTokenApi *api = [IGImageTokenApi new];
    api.requestPriority = YTKRequestPriorityHigh;
    [api startWithDecodeClass:[IGImageTokenResp class] CompletionBlockWithSuccess:^(id responseObject, NSError *error) {
        self.isRequesting = NO;
        if (responseObject) {
            IGImageTokenResp *resp = responseObject;
            IGImageTokenModel *model = resp.data;
            weakSelf.imageToken = model.imageToken;
            [weakSelf.imageToken configBucketPath:type];
            
            OSSFederationToken * token = [[OSSFederationToken alloc] init];
            token.tAccessKey = weakSelf.imageToken.accessKeyId;
            token.tSecretKey = weakSelf.imageToken.accessKeySecret;
            token.tToken = weakSelf.imageToken.securityToken;
            token.expirationTimeInGMTFormat = weakSelf.imageToken.expiration;
            
            id<OSSCredentialProvider> credential = [[OSSFederationCredentialProvider alloc] initWithFederationTokenGetter:^OSSFederationToken * {
                return token;
            }];
            self.client = [[OSSClient alloc] initWithEndpoint:weakSelf.imageToken.endpoint credentialProvider:credential];
            self.client.clientConfiguration.enableBackgroundTransmitService = NO;
            self.client.clientConfiguration.timeoutIntervalForRequest = 60;
            self.client.clientConfiguration.maxRetryCount = 2;
            self.client.clientConfiguration.isHttpdnsEnable = YES;
        }
    }];
}

- (void)asyncPutImages:(NSArray<UIImage *> *)images withCompleteBlock:(void (^)(NSArray *params, NSArray *urls))completeBlock {
    [self asyncPutImages:images withCompleteBlock:completeBlock progressBlock:nil isProduct:NO];
}

- (void)asyncPutImages:(NSArray<id> *)images withCompleteBlock:(void (^)(NSArray *params, NSArray *urls))completeBlock progressBlock:(void (^)(CGFloat progress, int index))progressBlock isProduct:(BOOL)isProduct {
    NSMutableArray *params = [NSMutableArray arrayWithArray:images];
    NSMutableArray *paramsTemp = [NSMutableArray array];//临时辅助作用
    __weak typeof(self) weakSelf = self;
    
    NSData *data;
    BOOL needProgress = NO;
    if (progressBlock) {//isProduct==TRUE + 批量上传需要上传的进度条
        needProgress = YES;
        for (int i = 0; i < images.count; i++) {
            __block int index = i;
            id image = [images objectAtIndex:i];
            if([image isKindOfClass:[UIImage class]]) {
                data = UIImageJPEGRepresentation(image, 0.8);
                [weakSelf asyncPutImagesData:data withCompleteBlock:^(NSString *picParam, NSError *error) {
                    if (picParam) {
                        [params replaceObjectAtIndex:index withObject:picParam];
                        [paramsTemp addObject:picParam];
                        
                        if (paramsTemp.count == images.count) {
                            completeBlock(params, nil);
                        }
                    } else {
                        completeBlock(nil, nil);
                    }
                } progressBlock:^(CGFloat progress) {
                    progressBlock(progress, index);
                } needProgress:YES];
            } else {
                [[TZImageManager manager] getOriginalPhotoWithAsset:image completion:^(UIImage *photo, NSDictionary *info) {
                    NSData *dataOri = UIImageJPEGRepresentation(photo, 0.8);
                    [weakSelf asyncPutImagesData:dataOri withCompleteBlock:^(NSString *picParam, NSError *error) {
                        if (picParam) {
                            [params replaceObjectAtIndex:index withObject:picParam];
                            [paramsTemp addObject:picParam];
                            
                            if (paramsTemp.count == images.count) {
                                completeBlock(params, nil);
                            }
                        } else {
                            completeBlock(nil, nil);
                        }
                    } progressBlock:^(CGFloat progress) {
                        progressBlock(progress, index);
                    } needProgress:YES];
                }];
            }
        }
        return;
    }
    
    for (int i = 0; i < images.count; i++) {
        __block int index = i;
        id image = [images objectAtIndex:i];
        if (isProduct) {//单张上传的是作品
            if([image isKindOfClass:[UIImage class]]) {
                data = UIImageJPEGRepresentation(image, 1.0);
                [weakSelf asyncPutImagesData:data withCompleteBlock:^(NSString *picParam, NSError *error) {
                    if (picParam) {
                        [params replaceObjectAtIndex:index withObject:picParam];
                        [paramsTemp addObject:picParam];
                        
                        if (paramsTemp.count == images.count) {
                            completeBlock(params, nil);
                        }
                    } else {
                        completeBlock(nil, nil);
                    }
                }];
            }
        } else {
            data = [UIImage compressImage:image];
            [self asyncPutImagesData:data withCompleteBlock:^(NSString *picParam, NSError *error) {
                if (picParam) {
                    [params replaceObjectAtIndex:index withObject:picParam];
                    [paramsTemp addObject:picParam];
                    
                    if (paramsTemp.count == images.count) {
                        completeBlock(params, nil);
                    }
                } else {
                    completeBlock(nil, nil);
                }
            }];
        }
    }
}

//重新请求token，而不关心过期时间
- (void)alwaysRequestImageToken {
    [self requestOssToken:self.type withCheckExpiration:NO];
}

//上传单个图片原始数据
- (void)asyncPutImagesData:(NSData *)data withCompleteBlock:(void (^)(NSString *picParam, NSError  *error))completeBlock {
    [self asyncPutImagesData:data withCompleteBlock:completeBlock progressBlock:nil needProgress:NO];
}

- (void)asyncPutImagesData:(NSData *)data withCompleteBlock:(void (^)(NSString *picParam, NSError  *error))completeBlock progressBlock:(void (^)(CGFloat progress))progressBlock needProgress:(BOOL)needProgress {
    __block int64_t allBytesSent = 0;
    __block int64_t allBytesExpectedToSend = data.length;
    /**
     * 上传OSS objectKey: EA46BA1CC44AB49ECA91E697796742.jpg
     */
    NSString *objectKey = [[NSString stringWithFormat:@"%@/%@.jpg", self.imageToken.bucketPath, [NSString uuidString]] stringByReplacingOccurrencesOfString:@"-" withString:@""];
    __weak typeof(self) weakSelf = self;
    
    self.putRequest = [[OSSPutObjectRequest alloc] init];
    self.putRequest.bucketName = self.imageToken.bucketName;
    self.putRequest.objectKey = objectKey;
    self.putRequest.uploadingData = data;
    if (needProgress) {
        self.putRequest.uploadProgress = ^(int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend) {
            allBytesSent += bytesSent;
            NSInteger progress = (int)((allBytesSent * 100) / allBytesExpectedToSend);
            dispatch_async(dispatch_get_main_queue(), ^{
                if (progressBlock) {
                    progressBlock(progress/100.0);
                }
            });
        };
    }
    OSSTask *task = [self.client putObject:self.putRequest];
    
    if (!task || !self.imageToken.accessKeyId) {
        completeBlock(nil, nil);
        [self alwaysRequestImageToken];
        return;
    }
    
    [task continueWithBlock:^id(OSSTask *task) {
        if (!task.error) {//图片上传成功
            //格式 picParam: bucketPoint/folderName/EA46BA1CC44AB49ECA91E697796742.jpg
            NSString *picParam = [NSString stringWithFormat:@"%@/%@", weakSelf.imageToken.bucketPoint, objectKey];
            completeBlock(picParam, nil);
        } else {//图片上传失败
            //-403 token过期
            if (task.error.code == -403) {
                [weakSelf alwaysRequestImageToken];
            }
            completeBlock(nil, nil);
        }
        weakSelf.putRequest = nil;
        
        return nil;
    }];
}
@end
